package com.yanqu.road.server.gameplayer.module.manor;

import com.yanqu.road.entity.config.manor.ManorConfig;
import com.yanqu.road.entity.config.manor.ManorGuestConfig;
import com.yanqu.road.entity.config.manor.ManorUpgradeConfig;
import com.yanqu.road.entity.config.skill.SkillInfo;
import com.yanqu.road.entity.config.skill.SkillUpgradeInfo;
import com.yanqu.road.entity.config.skin.SkinInfo;
import com.yanqu.road.entity.enums.*;
import com.yanqu.road.entity.log.LogManorHarvest;
import com.yanqu.road.entity.log.LogManorOutPutLvUp;
import com.yanqu.road.entity.log.LogManorSpecialSkillLvUp;
import com.yanqu.road.entity.manor.ManorHarvestData;
import com.yanqu.road.entity.manor.ManorRankActivityData;
import com.yanqu.road.entity.messageSubscribe.entity.MessageUserNoticeData;
import com.yanqu.road.entity.servercenter.GameEditLimit;
import com.yanqu.road.entity.servercenter.ServerInfo;
import com.yanqu.road.entity.task.args.ManorArgs;
import com.yanqu.road.entity.task.args.ManorRechargeArgs;
import com.yanqu.road.logic.bussiness.player.UserManorBusiness;
import com.yanqu.road.logic.config.ChannelConfig;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.pb.manor.ManorProto;
import com.yanqu.road.server.GameServer;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.player.AttributeModule;
import com.yanqu.road.server.gameplayer.module.player.CurrencyModule;
import com.yanqu.road.server.gameplayer.module.player.EarnSpeedModule;
import com.yanqu.road.server.gameplayer.module.skin.SkinModule;
import com.yanqu.road.server.manger.ConfigMgr;
import com.yanqu.road.server.manger.ForbiddenWordMgr;
import com.yanqu.road.server.manger.GameEditLimitMgr;
import com.yanqu.road.server.manger.ServerListMgr;
import com.yanqu.road.server.manger.activity.NormalActivityMgr;
import com.yanqu.road.server.manger.activity.curio.CurioMgr;
import com.yanqu.road.server.manger.config.SkillMgr;
import com.yanqu.road.server.manger.config.SkinMgr;
import com.yanqu.road.server.manger.config.SystemOpenMgr;
import com.yanqu.road.server.manger.log.LogMgr;
import com.yanqu.road.server.manger.manor.ManorMgr;
import com.yanqu.road.server.manger.messagesubscribe.MessageSubscribeMgr;
import com.yanqu.road.server.protocol.ClientProtocol;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;
import com.yanqu.road.utils.string.StringUtils;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;

/**
 * @author ：zfr
 * @date ：2021/5/10 18:31
 */
public class ManorHarvestModel {
    private Map<Integer, ManorHarvestData> harvestDataMap;
    private GamePlayer player;
    private int MANOR_MAX_NICK_NAME_LENGTH = 8;
    private int MANOR_MIN_NICK_NAME_LENGTH = 4;

    public ManorHarvestModel(Map<Integer, ManorHarvestData> dataMap, GamePlayer player) {
        this.harvestDataMap = dataMap;
        this.player = player;
    }


    public Map<Integer, ManorHarvestData> getHarvestDataMap() {
        return harvestDataMap;
    }

    /**
     * 解锁
     *
     * @param outPutId
     */
    public int unLock(int outPutId) {
        //是否已经解锁
        if (harvestDataMap.get(outPutId) != null) {
            return GameErrorCode.E_MANOR_OBJ_IS_UNLOCK;
        }
        //找配置
        ManorConfig manorConfig = ManorMgr.getManorConfigMap().get(outPutId);
        if (manorConfig == null) {
            return GameErrorCode.E_MANOR_CONFIG_NO_FOUND;
        }
        //身份是否达到
        if (player.getUserInfo().getTitleId() < manorConfig.getUnlock()) {
            return GameErrorCode.E_MANOR_TITLE_ID_LIMIT;
        }
        //牧场是否已建造 农场地块是否已开垦
        if (manorConfig.getType() <= 100) {
            int unLockLandIndex = player.getModule(ManorModule.class).getUserManorData().getFarmLandUnLock();
            if (manorConfig.getPosition() > unLockLandIndex * 16) {
                return GameErrorCode.E_MANOR_LAND_IS_LOCK;
            }
        } else if (manorConfig.getType() <= 200) {
            if (!player.getModule(ManorModule.class).getBuildingModel().getBuildingDataMap().containsKey(ManorMgr.getManorRanchId())) {
                return GameErrorCode.E_MANOR_RANCH_IS_LOCK;
            }
        }
        if (!player.getModule(CurrencyModule.class).removeCurrency(PropertyHelper.parseStringToProperty(manorConfig.getUnlockConsume()), eLogMoneyType.Manor, eLogMoneyType.ManorUnLockObjCost)) {
            return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
        }
        //解锁
        ManorHarvestData manorHarvestData = new ManorHarvestData();
        manorHarvestData.setUserId(player.getUserId());
        manorHarvestData.setOutPutId(outPutId);
        manorHarvestData.setHarvestType(manorConfig.getType());
        manorHarvestData.setLv(1);
        manorHarvestData.setSpecialSkillLv(1);
        manorHarvestData.setSkinId(initSkinId(manorConfig.getType()));
        manorHarvestData.setYieldStash(0L);
        long initTime = initCollectTime(isFirstUnLock(manorConfig));
        manorHarvestData.setCollectTime(initTime);
        manorHarvestData.setRealCollectTime(initTime);
        manorHarvestData.setNickName("");
        manorHarvestData.setChangeNameTimes(0);
        manorHarvestData.setExtendParam("");
        manorHarvestData.setInsertOption();
        harvestDataMap.put(outPutId, manorHarvestData);
        //繁荣度奖励
        player.getModule(ManorModule.class).addProsperousValue(Long.valueOf(manorConfig.getPlantRewards()), "产出物解锁");
        player.getModule(ManorModule.class).syncManorData();
        player.getModule(EarnSpeedModule.class).scheduleAddSilver();
        return 0;
    }

    /**
     * 是否是第一次解锁动物或者植物
     *
     * @param manorConfig
     * @return
     */
    public boolean isFirstUnLock(ManorConfig manorConfig) {
        if (manorConfig.getType() <= 100) { //植物
            for (ManorHarvestData harvestData : harvestDataMap.values()) {
                if (harvestData.getHarvestType() <= 100) {
                    return false;
                }
            }
            return true;
        } else if (manorConfig.getType() > 100 && manorConfig.getType() <= 200) {   //动物
            for (ManorHarvestData harvestData : harvestDataMap.values()) {
                if (harvestData.getHarvestType() > 100 && harvestData.getHarvestType() <= 200) {
                    return false;
                }
            }
            return true;
        }
        return false;
    }

    private int initSkinId(int type) {
        for (ManorHarvestData harvestData : harvestDataMap.values()) {
            if (harvestData.getHarvestType() == type) {
                return harvestData.getSkinId();
            }
        }
        int linkageSwitch;
        boolean useReview = false;
        int channelId = ServerListMgr.getChannelId(GameServer.getInstance().getServerId());
        if(eChannelType.isMainLandChannel(channelId)){
            ServerInfo serverInfo = ServerListMgr.getServerInfo(GameServer.getInstance().getServerId());
            if(null != serverInfo && serverInfo.getServerType() == ServerListMgr.SERVER_TYPE_REVIEW){//提审服用提审配置
                useReview = true;
            }
        }
        if(useReview){
            linkageSwitch = ChannelConfig.LIN_LEE_LINKAGE_SWITCH_REVIEW;
        }else {
            linkageSwitch = ChannelConfig.LIN_LEE_LINKAGE_SWITCH;
        }
        if (linkageSwitch == 1) {//联动
            if (ConfigMgr.getLinLeeSkinReplaceType() == type) {
                return ConfigMgr.getLinLeeSkinReplaceId();
            }
        }
        return 0;
    }

    /**
     * 初始化种植时间
     *
     * @param firstUnLock
     * @return
     */
    private long initCollectTime(boolean firstUnLock) {
        long curTime = System.currentTimeMillis();
        if (harvestDataMap.size() == 0) {
            return curTime - DateHelper.MINUTE_MILLIONS;
        }
        long lastSecondMillis = 0L;
        for (ManorHarvestData data : harvestDataMap.values()) {
            lastSecondMillis = data.getCollectTime() % DateHelper.MINUTE_MILLIONS;
            break;
        }
        long curSecondMillis = curTime % DateHelper.MINUTE_MILLIONS;
        long gapSecondMillis = curSecondMillis - lastSecondMillis;
        if (gapSecondMillis < 0 || firstUnLock) {
            gapSecondMillis = gapSecondMillis + DateHelper.MINUTE_MILLIONS;
        }
        return curTime - gapSecondMillis;
    }

    /**
     * 动物产出结算
     */
    public void calcAnimalYield(){
        long nowTime = System.currentTimeMillis();
        for (Map.Entry<Integer, ManorHarvestData> entry : harvestDataMap.entrySet()) {
            ManorHarvestData harvestData = entry.getValue();
            int outPutId = harvestData.getOutPutId();
            ManorConfig manorConfig = ManorMgr.getManorConfigMap().get(outPutId);
            if(manorConfig == null){
                continue;
            }
            if(manorConfig.getType() > 100 && manorConfig.getType() <= 200) {
                calcYield(harvestData, nowTime, false);
            }
        }
    }

    /**
     * 升级
     */
    public int levelUp(int outPutId, int levelUpCount) {
        //是否已经解锁
        ManorHarvestData manorHarvestData = harvestDataMap.get(outPutId);
        if (null == manorHarvestData) {
            return GameErrorCode.E_MANOR_OBJ_IS_LOCK;
        }
        ManorConfig manorConfig = ManorMgr.getManorConfigMap().get(outPutId);
        if (manorConfig == null) {
            return GameErrorCode.E_MANOR_CONFIG_NO_FOUND;
        }
        if (levelUpCount > 1) {
            if (player.getModule(ManorModule.class).getUserManorData().getProsperousValue() < GameConfig.MANOR_TEN_UPGRADE_UNLOCK_PROSPEROUS_VALUE_LIMIT) {
                return GameErrorCode.E_MANOR_PROSPEROUS_VALUE_NO_ENOUGH;
            }
        }
        //获取等级上限
        SkillInfo skillInfo = SkillMgr.getSkillInfo(Integer.parseInt(manorConfig.getSkill().split("\\|")[0]));
        int maxLv = skillInfo.getParamList().get(3);
        maxLv += (skillInfo.getUpgradeParamList().get(3) * (manorHarvestData.getSpecialSkillLv() - 1));
        int count;
        int lvCount = 0;
        BigDecimal totalRemoveSilver = BigDecimal.ZERO;
        for (count = 0; count < levelUpCount; count++) {
            ManorUpgradeConfig manorUpgradeConfig = ManorMgr.getManorUpgradeConfigMap().get(manorHarvestData.getLv() + 1);
            if (manorUpgradeConfig == null || manorHarvestData.getLv() >= maxLv) {
                if (0 == count) {
                    return GameErrorCode.E_MANOR_OBJ_IS_MAX_LEVEL;
                } else {
                    break;
                }
            }
            BigDecimal removeSilver = getLevelUpCost(outPutId, manorHarvestData.getLv());
            if (null == removeSilver) {
                if (0 == count) {
                    return GameErrorCode.E_MANOR_OBJ_IS_MAX_LEVEL;
                } else {
                    break;
                }
            }
            //消耗
            if (!player.getModule(CurrencyModule.class).removeCurrency(new Property(GameConfig.GAME_MONEY_SILVER, removeSilver.toBigInteger()),
                    eLogMoneyType.Manor, eLogMoneyType.ManorLevelUpCost)) {
                if (0 == count) {
                    return GameErrorCode.E_BAG_SILVER_NO_ENOUGH;
                } else {
                    break;
                }
            }
            //先算一下产出
            calcYield(manorHarvestData, System.currentTimeMillis(), false);
            //升级
            manorHarvestData.setLv(manorHarvestData.getLv() + 1);
            lvCount++;
            totalRemoveSilver = totalRemoveSilver.add(removeSilver);
        }
        player.getModule(ManorModule.class).addProsperousValue(lvCount * ManorMgr.getHarvestLvUpProsperousAdd(), "作物升级");
        player.notifyListener(eGamePlayerEventType.ManorObjectLevel.getValue(), new ManorArgs(harvestDataMap));
        player.getModule(ManorModule.class).syncManorData();
        LogMgr.addLogManorOutPutLvUp(new LogManorOutPutLvUp(player.getUserId(), manorHarvestData.getOutPutId(), lvCount, manorHarvestData.getLv(), totalRemoveSilver.toString(), new Date()));
        return 0;
    }

    public int levelUpTogether(int outPutId, int levelUpCount) {
        ManorHarvestData manorHarvestData = harvestDataMap.get(outPutId);
        if (null == manorHarvestData) {
            return GameErrorCode.E_MANOR_OBJ_IS_LOCK;
        }
        ManorConfig manorConfig = ManorMgr.getManorConfigMap().get(outPutId);
        if (manorConfig == null) {
            return GameErrorCode.E_MANOR_CONFIG_NO_FOUND;
        }

        ManorProto.ManorObjectLvUpRespMsg.Builder builder = ManorProto.ManorObjectLvUpRespMsg.newBuilder();
        builder.setRet(0);

        List<ManorHarvestData> sortList =new ArrayList<>();
        for (ManorHarvestData harvestData : harvestDataMap.values()) {
            if (harvestData.getHarvestType() != manorHarvestData.getHarvestType()) {
                continue;
            }

            sortList.add(harvestData);
        }

        sortList.sort(Comparator.comparingInt(ManorHarvestData::getOutPutId));

        for (ManorHarvestData harvestData : sortList) {
            ManorProto.ManorObjectLvUpResult.Builder resultBuilder = ManorProto.ManorObjectLvUpResult.newBuilder();
            int oldLv = harvestData.getLv();
            int ret = levelUp(harvestData.getOutPutId(), levelUpCount);
            resultBuilder.setId(harvestData.getOutPutId());
            resultBuilder.setRet(ret);
            if (ret == 0) {
                int newLv = harvestData.getLv();
                resultBuilder.setOldLv(oldLv);
                resultBuilder.setNewLv(newLv);
            }
            builder.addResult(resultBuilder);
        }



        player.sendPacket(ClientProtocol.U_MANOR_OBJECT_LV_UP, builder);
        return 0;
    }

    /**
     * 获取升级的花费
     */
    public BigDecimal getLevelUpCost(int outPutId, int lv) {
        ManorConfig manorConfig = ManorMgr.getManorConfigMap().get(outPutId);
        ManorUpgradeConfig manorUpgradeConfig = ManorMgr.getManorUpgradeConfigMap().get(lv);
        if (manorConfig != null && manorUpgradeConfig != null) {
            BigDecimal cost = new BigDecimal(manorConfig.getUpgradePar()).multiply(new BigDecimal(manorUpgradeConfig.getConsume())).divide(BigDecimal.valueOf(1000000));
            cost = cost.setScale(0, BigDecimal.ROUND_UP);
            return cost;
        }
        return null;
    }

    /**
     * 收获
     *
     * @return
     */
    public int harvest() {
        ManorProto.ManorHarvestRespMsg.Builder respMsg = harvestMsg();
        if (respMsg.getRet() != 0) {
            return respMsg.getRet();
        }
        player.getModule(AttributeModule.class).addAttribute(ePlayerAttrType.ManorTotalRewardTimes, 1);
        player.notifyListener(eGamePlayerEventType.RechargeManorNew.getValue(),  new ManorRechargeArgs(2, 0));
        player.sendPacket(ClientProtocol.U_MANOR_HARVEST, respMsg);
        return 0;
    }

    public ManorProto.ManorHarvestRespMsg.Builder harvestMsg() {
        ManorProto.ManorHarvestRespMsg.Builder respMsg = ManorProto.ManorHarvestRespMsg.newBuilder();
        if (!SystemOpenMgr.systemOpen(player, eSystemId.ManorSystem.getValue())) {//判断系统解锁
            respMsg.setRet(GameErrorCode.E_BAG_MANOR_SYSTEM_LOCK);
            return respMsg;    //未解锁
        }
        if (harvestDataMap.size() <= 0) {
            respMsg.setRet(GameErrorCode.E_MANOR_NO_HARVEST);
            return respMsg;    //没有作物
        }
        Property harvestReward = new Property();
        long nowTime = System.currentTimeMillis();
        for (ManorHarvestData harvestData : harvestDataMap.values()) {
            ManorConfig manorConfig = ManorMgr.getManorConfigMap().get(harvestData.getOutPutId());
            if (manorConfig == null) {
                continue;
            }
            calcYield(harvestData, nowTime, false);
            harvestData.setRealCollectTime(harvestData.getCollectTime());
            long yield = harvestData.getYieldStash();
            harvestReward.addProperty(new Property(manorConfig.getProduction(), BigInteger.valueOf(yield)));
            harvestData.setYieldStash(0L);
            String buildingArr = player.getModule(ManorModule.class).getBuildingArr();
            String guestArr = player.getModule(ManorModule.class).getGuestArr();
            BigDecimal baseSpeed = BigDecimal.valueOf(manorConfig.getProductionPar().get(0))
                    .add(BigDecimal.valueOf(manorConfig.getProductionPar().get(1)).multiply(new BigDecimal(harvestData.getLv() - 1)).divide(new BigDecimal(1000), 0, BigDecimal.ROUND_UP));
            LogMgr.addLogManorHarvest(new LogManorHarvest(player.getUserId(), manorConfig.getClassification(), manorConfig.getId(), harvestData.getLv(),
                    harvestData.getSpecialSkillLv(), harvestData.getSkinId(), buildingArr, guestArr, baseSpeed.longValue(), yield, new Date()));
        }
        if (harvestReward.isNothing()) {
            // 没有收获
            respMsg.setRet(GameErrorCode.E_MANOR_NO_REWARD);
            return respMsg;
        }

        player.getModule(CurrencyModule.class).addCurrency(harvestReward, eLogMoneyType.Manor, eLogMoneyType.ManorHarvestGet);
        //产量冲榜
        ManorMgr.harvestRank(harvestDataMap, player);
        respMsg.setRet(0);
        respMsg.setReward(PropertyHelper.parsePropertyToString(harvestReward));
        player.getModule(ManorModule.class).syncManorData();
        try {
            ManorRecoveryTime();
        }catch (Exception e){
            ManorMgr.getLogger().error("error:" + e);
        }
        return respMsg;
    }

    private void ManorRecoveryTime(){
        if(!MessageSubscribeMgr.isSwitch()){
            return;
        }
        long recoveryTime = 0;
        long maxAddTime = GameConfig.MANOR_OUTPUT_TIME_LIMIT * DateHelper.MINUTE_MILLIONS;
        long maxCollectTime = 0;
        for (ManorHarvestData harvestData : harvestDataMap.values()) {
            if(maxCollectTime < harvestData.getCollectTime()){
                maxCollectTime = harvestData.getCollectTime();
            }
        }
        recoveryTime = maxCollectTime + maxAddTime;
        MessageUserNoticeData noticeData = MessageSubscribeMgr.getUserNoticeData(player.getUserId());
        noticeData.setManorFoodTime(recoveryTime);
    }

    /**
     * 找回收益
     */
    public ManorProto.ManorHarvestRespMsg.Builder recoveryHarvest(int recoveryDay, int discount) {
        ManorProto.ManorHarvestRespMsg.Builder respMsg = ManorProto.ManorHarvestRespMsg.newBuilder();
        if (!SystemOpenMgr.systemOpen(player, eSystemId.ManorSystem.getValue())) {//判断系统解锁
            respMsg.setRet(GameErrorCode.E_BAG_MANOR_SYSTEM_LOCK);
            return respMsg;    //未解锁
        }
        if (harvestDataMap.size() <= 0) {
            respMsg.setRet(GameErrorCode.E_MANOR_NO_HARVEST);
            return respMsg;    //没有作物
        }
        Property harvestReward = new Property();
        for (ManorHarvestData harvestData : harvestDataMap.values()) {
            BigDecimal yield;
            ManorConfig manorConfig = ManorMgr.getManorConfigMap().get(harvestData.getOutPutId());
            if (manorConfig == null) {
                continue;
            }
            BigDecimal speed = calcSpeed(harvestData, false);
            //今日零点
            long todayZeroTime = DateHelper.getTodayZeroTimeStamp();
            //走那天的24点
            long leaveDayZeroTime = todayZeroTime - recoveryDay * DateHelper.DAY_MILLIONS;
            //收获满的时间
            long fullTime = harvestData.getRealCollectTime() + GameConfig.MANOR_OUTPUT_TIME_LIMIT * DateHelper.MINUTE_MILLIONS;
            //满几天的时间
            long originalTime = recoveryDay * DateHelper.DAY_MILLIONS;
            //如果走之后才收获满
            long needReduceTime = 0;
            if (leaveDayZeroTime < fullTime){
                //需要扣除
                needReduceTime = fullTime - leaveDayZeroTime;
            }
            long trueRecoveryTime = originalTime - needReduceTime;

            if (trueRecoveryTime <= 0){
                continue;
            }

            yield = speed.multiply(BigDecimal.valueOf(trueRecoveryTime/DateHelper.MINUTE_MILLIONS * discount / 1000));

            harvestReward.addProperty(new Property(manorConfig.getProduction(), yield.longValue()));

            String buildingArr = player.getModule(ManorModule.class).getBuildingArr();
            String guestArr = player.getModule(ManorModule.class).getGuestArr();
            BigDecimal baseSpeed = BigDecimal.valueOf(manorConfig.getProductionPar().get(0))
                    .add(BigDecimal.valueOf(manorConfig.getProductionPar().get(1)).multiply(new BigDecimal(harvestData.getLv() - 1)).divide(new BigDecimal(1000), 0, BigDecimal.ROUND_UP));
            LogMgr.addLogManorHarvest(new LogManorHarvest(player.getUserId(), manorConfig.getClassification(), manorConfig.getId(), harvestData.getLv(),
                    harvestData.getSpecialSkillLv(), harvestData.getSkinId(), buildingArr, guestArr, baseSpeed.longValue(), yield.longValue(), new Date()));
        }
        if (harvestReward.isNothing()) {
            // 没有收获
            respMsg.setRet(GameErrorCode.E_MANOR_NO_REWARD);
            return respMsg;
        }
        player.getModule(CurrencyModule.class).addCurrency(harvestReward, eLogMoneyType.Manor, eLogMoneyType.ManorHarvestGet);
        respMsg.setRet(0);
        respMsg.setReward(PropertyHelper.parsePropertyToString(harvestReward));
        player.getModule(ManorModule.class).syncManorData();
        try {
            ManorRecoveryTime();
        }catch (Exception e){
            ManorMgr.getLogger().error("error:" + e);
        }
        return respMsg;

    }

    /**
     * 计算收益
     *
     * @param data
     * @return
     */
    public void calcYield(ManorHarvestData data, long nowTime, boolean isCheckHelpRecover) {
        BigDecimal yield;
        ManorConfig manorConfig = ManorMgr.getManorConfigMap().get(data.getOutPutId());
        if (manorConfig == null) {
            return;
        }
        if (!isCheckHelpRecover) {
            checkManorHelpRecover(player);
        }
        BigDecimal speed = calcSpeed(data, true);
        //满出来了 不能再算了
        if (data.getCollectTime() - data.getRealCollectTime() >= GameConfig.MANOR_OUTPUT_TIME_LIMIT * DateHelper.MINUTE_MILLIONS) {
            data.setCollectTime(nowTime);
            return;
        }
        ManorMgr.addRankActivityYieldCount(data, nowTime, speed);
        long canCalcMin = GameConfig.MANOR_OUTPUT_TIME_LIMIT - ((data.getCollectTime() - data.getRealCollectTime()) / DateHelper.MINUTE_MILLIONS);
        long harvestMin = Math.min((nowTime - data.getCollectTime()) / DateHelper.MINUTE_MILLIONS, canCalcMin);
        long lastMillions = (nowTime - data.getCollectTime()) % DateHelper.MINUTE_MILLIONS;
        long collectTime = nowTime - lastMillions;
        data.setCollectTime(collectTime);
        yield = speed.multiply(new BigDecimal(harvestMin)).setScale(0, BigDecimal.ROUND_UP);
        data.setYieldStash(data.getYieldStash() + yield.longValue());
    }

    private void checkManorHelpRecover(GamePlayer player) {
        ManorMgr.checkManorHelpRecover(player);
    }

    public BigDecimal calcSpeed(ManorHarvestData data, boolean isCalcHelp) {
        BigDecimal baseSpeed = ManorMgr.calcBaseSpeed(data);
        BigDecimal skinAddRatio = ManorMgr.getSkinAddRatio(data, player.getModule(SkinModule.class).getUserSkinMap());
        BigDecimal specialAddRatio = ManorMgr.getSpecialAddRatio(data);
        BigDecimal guestAddRatio = ManorMgr.getGuestAddRatio(data, player.getModule(ManorModule.class).getGuestModel().getGuestDataMap());
        BigDecimal buildingAddRatio = ManorMgr.getBuildingAddRatio(data, player.getModule(ManorModule.class).getBuildingModel().getBuildingDataMap(), player.getModule(SkinModule.class).getUserSkinMap());
        //玩家协助加成
        BigDecimal helpAddRatio = BigDecimal.ZERO;
        if (isCalcHelp) {
            helpAddRatio = new BigDecimal(player.getUserInfo().getManorHelpCount() * GameConfig.MANOR_HEART_ADDITION_EFFECT);
            data.setHelpAddRatio(helpAddRatio.longValue());
        }
        data.setOtherAddRatio(skinAddRatio.add(guestAddRatio).add(buildingAddRatio).longValue());
        data.setSpecialSkillAddRatio(specialAddRatio.longValue());

        BigDecimal curioAddition = BigDecimal.ZERO;
        ManorConfig manorConfig = ManorMgr.getManorConfigMap().get(data.getOutPutId());
        if(manorConfig != null && manorConfig.getType() > 100 && manorConfig.getType() <= 200){
            //动物产量
            //藏品加成
            curioAddition = BigDecimal.valueOf(CurioMgr.getSkillAdditionBySkillType(eSkillType.ManorAnimalOutputSkill.getValue(), player, 0));
        }

        return baseSpeed.multiply(new BigDecimal(1000).add(specialAddRatio)).multiply(new BigDecimal(1000).add(skinAddRatio).add(guestAddRatio).add(curioAddition)
                .add(buildingAddRatio).add(helpAddRatio)).divide(BigDecimal.valueOf(1000 * 1000), 0, BigDecimal.ROUND_UP);
    }

    public void save() {
        for (ManorHarvestData harvestData : harvestDataMap.values()) {
            if (harvestData.isInsertOption()) {
                UserManorBusiness.add(harvestData);
            } else if (harvestData.isUpdateOption()) {
                UserManorBusiness.update(harvestData);
            }
        }
    }

    /**
     * 庄园物件改名
     *
     * @param id
     * @param nickName
     * @return
     */
    public int changeNickName(int id, String nickName) {
        ManorHarvestData manorHarvestData = harvestDataMap.get(id);
        if (manorHarvestData == null) {
            return GameErrorCode.E_MANOR_OBJ_IS_LOCK;
        }

        nickName = StringUtils.clearHeadAndTailEmpty(nickName);
        int nameLength = StringUtils.getStringLen(nickName);
        if (nameLength > MANOR_MAX_NICK_NAME_LENGTH || nameLength < MANOR_MIN_NICK_NAME_LENGTH) {
            return GameErrorCode.E_NAME_LENGTH_OVER;
        }

        if (ForbiddenWordMgr.isNickNameForbidden(nickName)) {
            return GameErrorCode.E_FORBIDDEN_WORD;
        }

        if(manorHarvestData.getChangeNameTimes() > 0){
            //编辑限制
            GameEditLimit gameEditLimit = GameEditLimitMgr.getGameEditLimit(Protocol.S_MANOR_OBJECT_CHANGE_NAME);
            if(null != gameEditLimit){
                long nowTime = System.currentTimeMillis();
                if(nowTime >= gameEditLimit.getLimitEditStartTime() && nowTime < gameEditLimit.getLimitEditEndTime()){
                    return GameErrorCode.E_SYSTEM_NO_OPEN;
                }
            }
        }
        //消耗
        BigInteger changeNickNameCost = getChangeNickNameCost(manorHarvestData.getChangeNameTimes());
        if (!player.getModule(CurrencyModule.class).removeCurrency(new Property(GameConfig.GAME_MONEY_INGOTS, changeNickNameCost), eLogMoneyType.Manor, eLogMoneyType.ManorChangeNameCost)) {
            return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
        }
        //改名
        manorHarvestData.setNickName(nickName);
        manorHarvestData.setChangeNameTimes(manorHarvestData.getChangeNameTimes() + 1);
        player.getModule(ManorModule.class).syncManorData();
        return 0;
    }

    /**
     * 获取改名消耗
     *
     * @param changeNameTimes
     * @return
     */
    private BigInteger getChangeNickNameCost(int changeNameTimes) {
        int cost = 0;
        if (changeNameTimes > 0) {
            String[] split = GameConfig.MANOR_OBJECT_CHANGE_NICKNAME_COST.split(";");
            cost = Integer.parseInt(split[0]) + ((changeNameTimes - 1) * Integer.parseInt(split[1]));
            if (cost > Integer.parseInt(split[2])) {
                cost = Integer.parseInt(split[2]);
            }
        }
        return BigInteger.valueOf(cost);
    }

    /**
     * 附属技能升级(土地、血统..)
     *
     * @param outPutId
     * @return
     */
    public int specialSkillLevelUp(int outPutId) {
        ManorHarvestData manorHarvestData = harvestDataMap.get(outPutId);
        if (manorHarvestData == null) {
            return GameErrorCode.E_MANOR_OBJ_IS_LOCK;
        }
        ManorConfig manorConfig = ManorMgr.getManorConfigMap().get(outPutId);
        if (manorConfig == null) {
            return GameErrorCode.E_MANOR_CONFIG_NO_FOUND;
        }
        SkillInfo skillInfo = SkillMgr.getSkillInfo(Integer.parseInt(manorConfig.getSkill().split("\\|")[0]));
        if (skillInfo == null) {
            return GameErrorCode.E_MANOR_SKILL_INFO_NO_FOUND;
        }
        if (skillInfo.getMaxLevel() < manorHarvestData.getSpecialSkillLv() + 1) {
            return GameErrorCode.E_MANOR_SKILL_LV_MAX;
        }
        SkillUpgradeInfo skillUpgradeInfo = SkillMgr.getSkillUpgradeInfo(skillInfo.getUpgradeType(0), manorHarvestData.getSpecialSkillLv());
        if (skillUpgradeInfo == null) {
            return GameErrorCode.E_MANOR_SKILL_INFO_NO_FOUND;
        }

        if (!player.getModule(CurrencyModule.class)
                .removeCurrency(new Property(skillInfo.getConsumeGoodsId().get(0), BigInteger.valueOf(skillUpgradeInfo.getConsumeCount())), eLogMoneyType.Manor, eLogMoneyType.ManorSpecialSkillLvUpCost)) {
            player.notifyListener(eGamePlayerEventType.RechargeManor.getValue(), new ManorRechargeArgs(1, 0));
            player.notifyListener(eGamePlayerEventType.RechargeManorNew.getValue(), new ManorRechargeArgs(1, 0));
            return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
        }
        //先算一下产出
        calcYield(manorHarvestData, System.currentTimeMillis(), false);
        player.getModule(ManorModule.class).addProsperousValue(ManorMgr.getSpecialSkillLvUpProsperousAdd() * skillUpgradeInfo.getConsumeCount(), "附属技能升级");
        manorHarvestData.setSpecialSkillLv(manorHarvestData.getSpecialSkillLv() + 1);
        player.getModule(ManorModule.class).syncManorData();
        player.getModule(EarnSpeedModule.class).scheduleAddSilver();
        LogMgr.addLogManorSpecialSkillLvUp(new LogManorSpecialSkillLvUp(player.getUserId(), manorConfig.getId(), skillInfo.getConsumeGoodsId().get(0) + "|" + skillUpgradeInfo.getConsumeCount(), manorHarvestData.getSpecialSkillLv(), new Date()));

        if(skillInfo.getMaxLevel() > manorHarvestData.getSpecialSkillLv() + 1){
            SkillUpgradeInfo newSkillUpgradeInfo = SkillMgr.getSkillUpgradeInfo(skillInfo.getUpgradeType(0), manorHarvestData.getSpecialSkillLv());
            if(newSkillUpgradeInfo != null){
                if(!player.getModule(CurrencyModule.class).currencyIsEnough(new Property(skillInfo.getConsumeGoodsId().get(0), BigInteger.valueOf(newSkillUpgradeInfo.getConsumeCount())))){
                    player.notifyListener(eGamePlayerEventType.RechargeManorNew.getValue(), new ManorRechargeArgs(1, 0));
                }
            }
        }
        return 0;
    }

    public int specialSkillLevelUpTogether(int outPutId) {
        ManorHarvestData manorHarvestData = harvestDataMap.get(outPutId);
        if (manorHarvestData == null) {
            return GameErrorCode.E_MANOR_OBJ_IS_LOCK;
        }
        ManorConfig manorConfig = ManorMgr.getManorConfigMap().get(outPutId);
        if (manorConfig == null) {
            return GameErrorCode.E_MANOR_CONFIG_NO_FOUND;
        }

        ManorProto.ManorSpecialSkillLevelUpRespMsg.Builder builder = ManorProto.ManorSpecialSkillLevelUpRespMsg.newBuilder();
        builder.setRet(0);

        List<ManorHarvestData> sortList = new ArrayList<>();
        for (ManorHarvestData harvestData : harvestDataMap.values()) {
            if (harvestData.getHarvestType() != manorHarvestData.getHarvestType()) {
                continue;
            }

            sortList.add(harvestData);
        }

        sortList.sort(Comparator.comparingInt(ManorHarvestData::getOutPutId));

        for (ManorHarvestData harvestData : sortList) {
            ManorProto.ManorObjectLvUpResult.Builder resultBuilder = ManorProto.ManorObjectLvUpResult.newBuilder();
            int oldLv = harvestData.getSpecialSkillLv();
            int ret = specialSkillLevelUp(harvestData.getOutPutId());
            resultBuilder.setId(harvestData.getOutPutId());
            resultBuilder.setRet(ret);
            if (ret == 0) {
                int newLv = harvestData.getSpecialSkillLv();
                resultBuilder.setOldLv(oldLv);
                resultBuilder.setNewLv(newLv);
            }
            builder.addResult(resultBuilder);
        }

        player.sendPacket(ClientProtocol.U_MANOR_OBJECT_SPECIAL_SKILL_LV_UP, builder);
        return 0;
    }

    /**
     * 通知皮肤加成变化
     *
     * @param skinInfo
     */
    public void notifySkinAdd(SkinInfo skinInfo) {
        int type = skinInfo.getBelongRole();
        long nowTime = System.currentTimeMillis();
        for (Integer skillId : skinInfo.getSkinEffect()) {
            SkillInfo skillInfo = SkillMgr.getSkillInfo(skillId);
            if (skillInfo != null) {
                if (skillInfo.getType() == -1) {
                    for (ManorHarvestData harvestData : harvestDataMap.values()) {
                        ManorConfig manorConfig = ManorMgr.getManorConfigMap().get(harvestData.getOutPutId());
                        if (manorConfig == null) {
                            continue;
                        }
                        if (manorConfig.getType() == type) {
                            calcYield(harvestData, nowTime, false);
                            player.getModule(ManorModule.class).syncManorData();
                        }
                    }
                } else {
                    notifySkillAdd(skillInfo);
                }
            }
        }
    }


    /**
     * 通知住客加成变化
     *
     * @param id
     */
    public void notifyGuestAdd(int id) {
        ManorGuestConfig manorGuestConfig = ManorMgr.getManorGuestConfigMap().get(id);
        if (manorGuestConfig == null) {
            return;
        }
        SkillInfo skillInfo = SkillMgr.getSkillInfo(manorGuestConfig.getSkill());
        if (skillInfo == null) {
            return;
        }
        notifySkillAdd(skillInfo);
    }

    /**
     * 通知建筑加成变化
     *
     * @param id
     */
    public void notifyBuildingAdd(int id) {
        ManorConfig manorConfig = ManorMgr.getManorConfigMap().get(id);
        if (manorConfig == null) {
            return;
        }
        SkillInfo skillInfo = SkillMgr.getSkillInfo(Integer.parseInt(manorConfig.getSkill()));
        if (skillInfo == null) {
            return;
        }
        notifySkillAdd(skillInfo);
    }

    public void notifySkillAdd(SkillInfo skillInfo) {
        Integer addType = skillInfo.getParamList().get(2);
        long nowTime = System.currentTimeMillis();
        for (ManorHarvestData harvestData : harvestDataMap.values()) {
            ManorConfig config = ManorMgr.getManorConfigMap().get(harvestData.getOutPutId());
            if (config == null) {
                continue;
            }
            if (addType == 0 || addType == config.getClassification()) {
                calcYield(harvestData, nowTime, false);
            }
        }
    }

    /**
     * 更换皮肤
     *
     * @param id
     * @param skinId
     * @return
     */
    public int changeSkin(int id, int skinId) {
        ManorConfig manorConfig = ManorMgr.getManorConfigMap().get(id);
        if (manorConfig == null) {
            return GameErrorCode.E_MANOR_CONFIG_NO_FOUND;
        }
        if (skinId != 0 && player.getModule(SkinModule.class).getUserSkin(skinId) == null) {
            return GameErrorCode.E_MANOR_SKIN_IS_LOCK;
        }
        int type = manorConfig.getType();
        if (skinId != 0) {
            SkinInfo skinInfo = SkinMgr.getSkinInfo(skinId);
            if (skinInfo == null) {
                return GameErrorCode.E_SKIN_NOT_EXIST;
            }
            if (skinInfo.getBelongRole() != type) {
                return GameErrorCode.E_SKIN_NOT_MATCH;
            }
        }
        for (ManorHarvestData harvestData : harvestDataMap.values()) {
            if (harvestData.getHarvestType() == type) {
                harvestData.setSkinId(skinId);
            }
        }
        player.getModule(ManorModule.class).syncManorData();
        return 0;
    }

    public void notifyGuestSkinAdd(int guestSkinId) {
        ManorGuestConfig manorGuestConfig = ManorMgr.getManorGuestConfigMap().get(guestSkinId);
        if (manorGuestConfig != null) {
            SkillInfo skillInfo = SkillMgr.getSkillInfo(manorGuestConfig.getSkill());
            if (skillInfo != null) {
                notifySkillAdd(skillInfo);
            }
        }
    }

    public boolean isUnLockClassification(int classification) {
        for (ManorHarvestData data : harvestDataMap.values()) {
            ManorConfig manorConfig = ManorMgr.getManorConfigMap().get(data.getOutPutId());
            if (manorConfig != null) {
                if (manorConfig.getClassification() == classification || classification == 0) {
                    return true;
                }
            }
        }
        return false;
    }

    public Property getUseGoodGet(int timeMin, int classification, long count) {
        Property getItem = new Property();
        if (classification == 0) {
            List<ManorHarvestData> list = new ArrayList<>(harvestDataMap.values());
            for (int i = 0; i < count; i++) {
                int randomIndex = new RandomHelper().next(list.size());
                ManorHarvestData data = list.get(randomIndex);
                ManorConfig manorConfig = ManorMgr.getManorConfigMap().get(data.getOutPutId());
                if (manorConfig != null) {
                    getItem.addProperty(manorConfig.getProduction(), BigInteger.valueOf(calcSpeed(data, false).multiply(BigDecimal.valueOf(timeMin)).longValue()));
                }
            }
        } else {
            for (ManorHarvestData data : harvestDataMap.values()) {
                ManorConfig manorConfig = ManorMgr.getManorConfigMap().get(data.getOutPutId());
                if (manorConfig != null && manorConfig.getClassification() == classification) {
                    getItem.addProperty(manorConfig.getProduction(), BigInteger.valueOf(calcSpeed(data, false).multiply(BigDecimal.valueOf(timeMin)).multiply(BigDecimal.valueOf(count)).longValue()));
                }
            }
        }
        return getItem;
    }

    public void removeActivityData() {
        //登陆后移除已过期的活动数据
        for (ManorHarvestData harvestData : harvestDataMap.values()) {
            boolean isUpdate = false;
            Map<Integer, ManorRankActivityData> rankActivityDataMap = harvestData.getRankActivityDataMap();
            if (rankActivityDataMap == null) {
                return;
            }
            synchronized (rankActivityDataMap) {
                List<Integer> needRemoveList = new ArrayList<>();
                for (ManorRankActivityData activityData : rankActivityDataMap.values()) {
                    List<Integer> activityIdList = NormalActivityMgr.getOpenManorRankActivityIdList();
                    if (!activityIdList.contains(activityData.getActivityId())) {
                        needRemoveList.add(activityData.getActivityId());
                        isUpdate = true;
                    }
                }
                for (Integer activityId : needRemoveList) {
                    rankActivityDataMap.remove(activityId);
                }
                if (isUpdate) {
                    harvestData.setUpdateOption();
                }
            }
        }
    }

    /**
    * 描述：变更暴富鸭皮肤
    * 作者：zrq
    * 时间：2023/6/12
    * 参数：

    * 返回值：
    **/
    public void changeLinLeeSkin(int type, int skinId) {
        if (0 != skinId) {
            SkinInfo skinInfo = SkinMgr.getSkinInfo(skinId);
            if (null == skinInfo) {
                return;
            }
            if (skinInfo.getBelongRole() != type) {
                return;
            }
        }
        for (ManorHarvestData harvestData : harvestDataMap.values()) {
            if (harvestData.getHarvestType() == type) {
                harvestData.setSkinId(skinId);
            }
        }
    }

    /**
    * 描述：linlee茶联动结束重置皮肤
    * 作者：zrq
    * 时间：2023/6/12
    * 参数：

    * 返回值：
    **/
    public boolean linLeeSkinCloseReset(int type, int skinId) {
        boolean isChange = false;
        for (ManorHarvestData harvestData : harvestDataMap.values()) {
            if (harvestData.getHarvestType() == type && harvestData.getSkinId() == skinId) {
                harvestData.setSkinId(0);
                isChange = true;
            }
        }
        return isChange;
    }
}
